Skip to content

fix(bridge): resume persisted session_id after restart when SDK transcript exists#325

Merged
seoseo-ai merged 3 commits into
mainfrom
fix/bridge-resume-persisted-session
Jul 8, 2026
Merged

fix(bridge): resume persisted session_id after restart when SDK transcript exists#325
seoseo-ai merged 3 commits into
mainfrom
fix/bridge-resume-persisted-session

Conversation

@seoseo-ai

Copy link
Copy Markdown
Collaborator

What

After a bridge restart, _effective_session_id rejected every persisted session_id because the in-memory _runtime_active_sessions set starts empty — every conversation began blank (bot "memory loss").

Why (evidence)

Diagnosed 2026-07-08 on daegyo node via controlled restart experiment: PATH1 CONFIRMEDIgnoring persisted session_id marker fired on the first post-restart message (10:37:37 KST); PATH2 (stale stream / reader crash) markers: 0.

Fix

  • Persisted session_id not in the runtime set is now auto-resumed iff its SDK conversation JSONL transcript exists under ~/.claude/projects/<project>/ (validated via resolve_conversation_file — traversal-safe).
  • Stale ids without a transcript are still ignored (original cross-process safety intent preserved; the Ignoring persisted session_id log marker kept for diagnostics).
  • Off-switch: CCC_RESUME_PERSISTED_SESSIONS=false restores old behavior. Documented in bridge/CLAUDE.md env table.
  • New pure helper core/session_resume.py per the extracted-helpers convention.

Test plan

  • tests/test_session_resume.py — 8/8 green (flag parsing, transcript exists/missing, traversal rejection, dir-not-file)
  • Full suite python -m unittest discover tests: 476 tests; same 7 pre-existing env failures reproduced on clean main (voice/path-scope, Termux env) — no regression
  • Post-merge: restart bridge on daegyo, confirm first message resumes prior session (no PATH1 marker)

🤖 Generated with Claude Code

…K transcript exists

After a bridge restart the in-memory _runtime_active_sessions set is empty,
so _effective_session_id rejected every persisted session_id ("Ignoring
persisted session_id ... not active in current runtime") and each
conversation started blank — diagnosed as PATH1 memory loss (2026-07-08,
daegyo node, diag-memory.sh: PATH1 marker x1, PATH2 markers 0).

Fix: a persisted session_id not in the runtime set is now auto-resumed when
its SDK conversation JSONL transcript still exists under
~/.claude/projects/<project>/ (validated via resolve_conversation_file, so
corrupt/traversal ids cannot escape the directory). Stale ids without a
transcript are still ignored, preserving the original cross-process safety
intent. Off-switch: CCC_RESUME_PERSISTED_SESSIONS=false restores the old
never-resume behavior.

- new pure helper core/session_resume.py (+8 unit tests, all green)
- full suite: 476 tests, same 7 pre-existing env failures on clean main
  (voice/path-scope, Termux env) — no regression from this change

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@seoseo-ai seoseo-ai requested a review from jinon86 as a code owner July 8, 2026 01:55

@jinon86 jinon86 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Root-cause fix (not a workaround): resumes a persisted session_id after bridge restart only when its SDK transcript still verifiably exists on disk (traversal-safe via resolve_conversation_file), otherwise still ignored. 8/8 new unit tests + full 476-test suite green, no regression. This directly explains today's daegyo memory-loss symptom (Ignoring persisted session_id fired on first post-restart message). Approving.

@seoseo-ai seoseo-ai merged commit 3e27223 into main Jul 8, 2026
7 checks passed
@seoseo-ai seoseo-ai deleted the fix/bridge-resume-persisted-session branch July 8, 2026 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants